<!DOCTYPE html>
<html>
    <head>
       <title>cavans点赞动画效果</title>
    </head>
    <body>
       <canvas onclick="tapAdd()" id="thumsCanvas" width="250" height="500" style="width:250px;height:500px;background-color: #f4f4f4;"></canvas>
    </body>
    <script>
        //图标动画类
        class Ani{
            constructor(img,x,y,w,h){
               this.x=x;
               this.y=y;
               this.width=w;
               this.height=h;
               this.image=img;
               //随机生成正弦曲线的波动幅度
               this.step=getRandom(10,60);
               //随机生成y轴的移动速度
               this.spite=getRandom(2,6);
               this.frequency=getRandom(50,100);
               //小图标透明度
               this.op=0;
               //随机曲线类型
               Math.random()>=0.5?this.type=1:this.type=2;
               this.dy=0;
            }
            draw(context){ 
               //y轴动画效果
                this.y-=this.spite;
               //x轴动画效果 
                this.dy+=this.spite;
                let dx=0;
                //不同的波动方向
                this.type==1?dx=Math.sin(this.dy/this.frequency):dx=Math.sin(-this.dy/this.frequency);
                let x=this.x+dx*this.step;  
                //图像放大动画
                if(this.width<50){
                   this.width+=0.5;
                   this.height+=0.5;
                }
                context.drawImage(this.image,x,this.y,this.width,this.height);
                //图像消失动画，透明度从0-1
                if(this.y<50){
                   this.op+=0.05
                   context.fillStyle = `rgba(255,255,255,${this.op})`;
                   context.fillRect(x,this.y,this.width,this.height);
                }
            }
        }
       //小图标动画对象数组
       let aniList=[];
       const canvas = document.getElementById('thumsCanvas');
       let imageList=[];
       let context = canvas.getContext('2d');
       //加载图像
       function loadImage(){
           const images=['./img/zan.png'];
           const promiseList=[];
           images.forEach(element => {
               let p=new Promise((resolve)=>{
                   const img=new Image();
                   img.onload=resolve.bind(null,img)
                   img.src=element;
               })
               promiseList.push(p)
           });
           return new Promise(resolve=>{
               Promise.all(promiseList).then(imgs=>{                        
                       this.imageList=imgs;
                       resolve();
               })
           })
       }
       //获取随机数
       function getRandom(min,max){
           return Math.floor(Math.random()*(max-min))+min
       }
       //添加图标
       function tapAdd(){
           let image=this.imageList[0];
           let ani=new Ani(image,250/2-50/2,500-50,20,20)
           aniList.push(ani)
       }
       //渲染函数
       function render(){
           //context.clearRect(0,0,250,500); // clear canvas
           context.fillStyle = 'rgba(255,255,255,0.5)';
           context.fillRect(0,0,250,500);
           aniList.forEach((ani,index)=>{
               if(ani.y<-50){
                   ani=null;
               }else{
                   ani.draw(context);
               }
           })
           window.requestAnimationFrame(render)
       }        
       loadImage().then(()=>{
           console.log('图像加载完成')
           render();
           setInterval(tapAdd,100);
       });
    </script>
</html>